package linker.account;

import java.io.FileNotFoundException;
import java.io.IOException;

import javax.swing.JFrame;

import linker.buddy.BuddyList;
import linker.list.FileRecieveMessage;
import linker.list.FunctionList;
import linker.list.ListItem;
import linker.list.MessageList;
import linker.list.StringMessage;
import linker.window.MainWindow;

import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smackx.filetransfer.FileTransferListener;
import org.jivesoftware.smackx.filetransfer.FileTransferManager;
import org.jivesoftware.smackx.filetransfer.FileTransferRequest;
import org.jivesoftware.smackx.packet.Version;

/**
 * The Account Class to manange account
 * 
 * @version linker 0.93
 * @author Jianfeng jianfeng.linker@gmail.com
 * 
 */
public class Account {

	// The roster
	private static Roster roster;

	// The XMPPConnection
	private static XMPPConnection connection;

	// The buddyList holds buddy information
	private static BuddyList buddyList;

	// The messageList holds messages
	private static MessageList messageList;

	// The functionList holds functions information
	private static FunctionList functionList;

	// The Main window of this software
	private static MainWindow window;

	// Self
	private static Account account = null;

	// The file transfer manager
	private static FileTransferManager fileTransferManager;

	/**
	 * Function getInstance()
	 * 
	 * @return account (Self)
	 */
	public static Account getAccount() {
		if (account == null)
			account = new Account();

		return account;
	}

	/**
	 * The login function
	 * 
	 * @param name
	 * @param password
	 * @return whether logined sucessed
	 */
	public boolean login(String name, String password, String host,
			String port, String domain) {

		if (!Connect.login(name, password, host, port, domain)) {
			return false;
		}

		// Get XMPPconnection
		connection = Connect.getConnecdtion();

		// Get Roster
		roster = connection.getRoster();

		// File buddylist and create message list
		roster.setSubscriptionMode(Roster.SubscriptionMode.manual);
		buddyList = new BuddyList();
		buddyList.fill(roster);
		messageList = new MessageList();
		try {
			functionList = new FunctionList();
			functionList.loadPlugins();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		// Send software version information ?
		Version version = new Version();
		version.setName("Linker");
		connection.sendPacket(version);

		/**
		 * Add packetListener and display every packet information
		 */
		connection.addPacketListener(new PacketListener() {
			public void processPacket(Packet packet) {

				// Display packet information to debug
				System.out.println(packet.toXML());

				if (packet instanceof Presence) {
					Presence presence = (Presence) packet;
					buddyList.changeByPresence(presence);
				} else if (packet instanceof Message) {
					Message message = (Message) packet;
					buddyList.processMessage(message);
				}
			}
		}, new PacketFilter() {
			public boolean accept(Packet packet) {
				return true;
			}
		});

		fileTransferManager = new FileTransferManager(connection);
		fileTransferManager.addFileTransferListener(new FileTransferListener() {

			public void fileTransferRequest(FileTransferRequest request) {
				addMessage(new FileRecieveMessage(request));
			}

		});

		return true;
	}

	/**
	 * Get user name
	 * 
	 * @return
	 */
	public static String getName() {
		String name = connection.getUser();
		name = name.substring(0, name.indexOf('@'));

		return name;
	}

	/**
	 * Get roster
	 * 
	 * @return roster
	 */
	public static Roster getRoster() {
		return roster;
	}

	/**
	 * Get XMPPConnection
	 * 
	 * @return xmppconnection
	 */
	public static XMPPConnection getConnection() {
		return connection;
	}

	/**
	 * Send packet
	 * 
	 * @param packet
	 */
	public static void sendPacket(Packet packet) {
		connection.sendPacket(packet);
	}

	/**
	 * Get buddy list
	 * 
	 * @return buddyList
	 */
	public static BuddyList getBuddyList() {
		return buddyList;
	}

	/**
	 * Add new message to message list
	 * 
	 * @param newMessage
	 */
	public static void addMessage(ListItem newMessage) {
		messageList.addMessage(newMessage);

		setStatus();
	}

	public static void addStringMessage(String m, JFrame window) {
		messageList.addMessage(new StringMessage(m, window));
	}

	public static void removeMessage(ListItem message) {
		messageList.removeMessage(message);

		setStatus();
	}

	public static MessageList getMessageList() {
		return messageList;
	}

	public static FunctionList getFunctionList() {

		return functionList;
	}

	public void setMainWindow(MainWindow window) {
		Account.window = window;
	}

	public static void setStatus() {
		window.setStatus();
	}

	public static FileTransferManager getFileTransferManager() {
		return fileTransferManager;
	}

	public static void disconnect() {
		connection.disconnect();
	}
}
